/**
 * 
 */

package com.pp.admin.main.client.tab.objectpages;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.pp.admin.common.client.beans.Phone;
import com.pp.admin.common.client.helper.AdminFlexTable;
import com.pp.admin.common.client.helper.AdminFormTextBox;
import com.pp.admin.common.client.helper.Resource;
import com.pp.admin.common.client.i18.I18;

/**
 * @author pandurang
 */
public class PhoneInfo extends AdminFlexTable {

	static final int PHONE_INFO_LBL_ROW = 0;

	static final int REQ_PHONE_ROW = 1;

	static final int NO_TABLE_COLS = 5;

	static final int RADIO_GRP_COL = 0;

	static final int LABEL_COL = 1;

	static final int FIELD_COL = 2;

	static final int TYPE_COL = 3;

	static final int ADD_REMOVE_COL = 4;

	static final String MY_PHONE_GRP = "phoneGroup";

	/**
	 * TODO take max limit from the property file so that it will be easily
	 * configurable.
	 */
	private static final int MAX_PHONE_LMT = 5;

	private static final int MIN_PHONE_LMT = 1;

	private int noOfPhones = 0;

	private int currentAddLinkRow = REQ_PHONE_ROW;

	private PhoneNode firstNode = null;

	private PhoneNode lastNode = null;

	private Image addLink = new Image(Resource.ADD_IMG_URL);

	class RemoveHandler implements ClickHandler {

		private PhoneNode node = null;

		RemoveHandler(PhoneNode node) {

			this.node = node;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt
		 * .event.dom.client. ClickEvent)
		 */
		@Override
		public void onClick(ClickEvent event) {

			removePhone(node);
		}

	}

	public PhoneInfo(List<Phone> phones) {
		init();
		if (phones.size() == 0) {
			addPhone(null);
		} else {
			Phone phone = null;
			for (Iterator<Phone> iterator = phones.iterator(); iterator
					.hasNext();) {
				phone = iterator.next();
				addPhone(phone);
			}
		}
	}

	public PhoneInfo() {
		init();
		addPhone(null);
	}

	public void init() {
		this.setWidget(PHONE_INFO_LBL_ROW, LABEL_COL, new Label(myConstants
				.phoneinfo()
				+ " : "));
		this.setTdAttribute(PHONE_INFO_LBL_ROW, LABEL_COL,
				AdminFlexTable.ATR_TD_COLSPAN, "" + NO_TABLE_COLS);
		this.setWidget(currentAddLinkRow, ADD_REMOVE_COL, addLink);
		addLink.setHeight(Resource.ACTION_IMG_HIGHT);
		addLink.setWidth(Resource.ACTION_IMG_WIDTH);
		addLink.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {

				addPhone(null);
			}
		});

	}

	private void removePhone(PhoneNode node) {

		if (noOfPhones != MIN_PHONE_LMT) {

			removeRow(node.getRowNo());

			PhoneNode prev = node.getPrev();
			PhoneNode next = node.getNext();
			if (prev == null && next == null) {
				firstNode = lastNode = null;
			} else if (prev == null && next != null) {
				firstNode = next;
				next.getSelected().setValue(true);
			} else if (next == null && prev != null) {
				lastNode = prev;
			}
			node.remove();
			currentAddLinkRow--;
			if (noOfPhones == MAX_PHONE_LMT) {
				addLink.setVisible(true);
			}
			noOfPhones--;
		}
	}

	private void addPhone(Phone phone) {

		this.insertRow(currentAddLinkRow);
		PhoneNode node = null;
		if (phone == null) {
			node = new PhoneNode(currentAddLinkRow, this);
		} else {
			node = new PhoneNode(currentAddLinkRow, this, phone);
		}
		this.setWidget(currentAddLinkRow, RADIO_GRP_COL, node.getSelected());
		this.setWidget(currentAddLinkRow, LABEL_COL, new Label(myConstants
				.phone()
				+ " : "));
		this.getCellFormatter().setHorizontalAlignment(currentAddLinkRow,
				LABEL_COL, HasHorizontalAlignment.ALIGN_RIGHT);
		this.setWidget(currentAddLinkRow, FIELD_COL, node.getPhoneFiled());
		this.setWidget(currentAddLinkRow, TYPE_COL, node.getType());
		if (firstNode == null) {
			firstNode = lastNode = node;
			node.getSelected().setValue(true);
		} else {
			lastNode.setNext(node);
			lastNode = node;
			this.setWidget(currentAddLinkRow, ADD_REMOVE_COL, node
					.getRemoveLink());
		}
		currentAddLinkRow++;
		noOfPhones++;
		if (noOfPhones == MAX_PHONE_LMT) {
			addLink.setVisible(false);
		}
	}

	public List<Phone> getPhoneList() {

		List<Phone> list = new ArrayList<Phone>();
		PhoneNode node = firstNode;
		while (node != null) {
			list.add(node.getPhone());
			node = node.getNext();
		}
		return list;
	}
}

class PhoneNode {

	private PhoneInfo parent = null;

	private Phone phone = new Phone();

	private int rowNo;

	private AdminFormTextBox phoneFiled = new AdminFormTextBox();

	private PhoneType type = new PhoneType();

	private Image removeLink = new Image(Resource.REMOVE_IMG_URL);

	private RadioButton selected = new RadioButton(PhoneInfo.MY_PHONE_GRP);

	private PhoneNode next = null;

	private PhoneNode prev = null;

	public PhoneNode(int rowNo, PhoneInfo parent, Phone phone) {
		this(rowNo, parent);
		this.phone = phone;
		phoneFiled.setText(phone.getPhoneNo());
		type.setSelectedIndex(phone.getPhoneType() - 1);
		if (phone.isPrimary()) {
			selected.setValue(true);
		}
	}

	public PhoneNode(int rowNo, PhoneInfo parent) {

		this.parent = parent;
		this.rowNo = rowNo;
		removeLink.setHeight(Resource.ACTION_IMG_HIGHT);
		removeLink.setWidth(Resource.ACTION_IMG_WIDTH);
		removeLink.addClickHandler(parent.new RemoveHandler(this));
	}

	public Phone getPhone() {

		phone.setPhoneNo(phoneFiled.getTextBox().getText());
		phone.setPhoneType(Byte.parseByte(type
				.getValue(type.getSelectedIndex())));
		phone.setPrimary(selected.getValue());
		return phone;
	}

	public void remove() {

		if (prev != null) {
			prev.setNext(next);
		} else if (next != null) {
			next.setPrev(prev);
		}
		if (next != null) {
			next.slideUp();
		}
	}

	public void slideUp() {

		rowNo--;
		if (next != null) {
			next.slideUp();
		}
	}

	/**
	 * @return the phoneFiled
	 */
	public AdminFormTextBox getPhoneFiled() {

		return phoneFiled;
	}

	/**
	 * @param phoneFiled
	 *            the phoneFiled to set
	 */
	public void setPhoneFiled(AdminFormTextBox phoneFiled) {

		this.phoneFiled = phoneFiled;
	}

	/**
	 * @return the type
	 */
	public PhoneType getType() {

		return type;
	}

	/**
	 * @param type
	 *            the type to set
	 */
	public void setType(PhoneType type) {

		this.type = type;
	}

	/**
	 * @return the removeLink
	 */
	public Image getRemoveLink() {

		return removeLink;
	}

	/**
	 * @param removeLink
	 *            the removeLink to set
	 */
	public void setRemoveLink(Image removeLink) {

		this.removeLink = removeLink;
	}

	/**
	 * @return the selected
	 */
	public RadioButton getSelected() {

		return selected;
	}

	/**
	 * @param selected
	 *            the selected to set
	 */
	public void setSelected(RadioButton selected) {

		this.selected = selected;
	}

	/**
	 * @return the next
	 */
	public PhoneNode getNext() {

		return next;
	}

	/**
	 * @param next
	 *            the next to set
	 */
	public void setNext(PhoneNode next) {

		this.next = next;
		if (next != null) {
			next.setPrev(this);
		}
	}

	/**
	 * @return the prev
	 */
	public PhoneNode getPrev() {

		return prev;
	}

	/**
	 * @param prev
	 *            the prev to set
	 */
	public void setPrev(PhoneNode prev) {

		this.prev = prev;
	}

	/**
	 * @return the rowNo
	 */
	public int getRowNo() {

		return rowNo;
	}

}

class PhoneType extends ListBox implements I18 {

	public static final String TYPE_HOME = myConstants.home();

	public static final String TYPE_OFFICE = myConstants.office();

	public static final String TYPE_MOBILE = myConstants.mobile();

	public static final String TYPE_FAX = myConstants.fax();

	public static final String TYPE_OTHER = myConstants.other();

	public PhoneType() {

		this.addItem(TYPE_HOME, Phone.TYPE_HOME + "");
		this.addItem(TYPE_OFFICE, Phone.TYPE_OFFICE + "");
		this.addItem(TYPE_MOBILE, Phone.TYPE_MOBILE + "");
		this.addItem(TYPE_FAX, Phone.TYPE_FAX + "");
		this.addItem(TYPE_OTHER, Phone.TYPE_OTHER + "");
		this.setSelectedIndex(0);
	}

	public byte getSeletedPhoneType() {

		return Byte.parseByte(this.getValue(this.getSelectedIndex()));
	}

}
